import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.Key;
import java.util.Scanner;
import java.net.*;
public class Client2 {
    public static void main(String[] args) {
        String mode = "AES";
        //客户端让用户输入中缀表达式，然后把中缀表达式调用MyBC.java的功能转化为后缀表达式，把后缀表达式通过网络发送给服务器
        Scanner scanner = new Scanner(System.in);
        Socket mysocket;
        DataInputStream in = null;
        DataOutputStream out = null;
        try {
            mysocket = new Socket("127.0.0.1", 2010);
            in = new DataInputStream(mysocket.getInputStream());
            out = new DataOutputStream(mysocket.getOutputStream());
            System.out.println("客户端已连接成功：");
            String formula = scanner.nextLine();
            String regex = ".*[^0-9|+|\\-|*|÷|(|)|\\s|/].*";
            if (formula.matches(regex)) {
                System.out.println("输入了非法字符");
                System.exit(1);
            }
            String output = "";
            MyBC myBC = new MyBC();
            try {
                //中缀转后缀
                output = MyBC.getrp(formula);
            } catch (Exception e) {
                System.out.println(e.getMessage());
                System.exit(1);
            }
            //使用AES进行后缀表达式的加密
            KeyGenerator kg = KeyGenerator.getInstance(mode);
            kg.init(128);
            SecretKey k = kg.generateKey();//生成密钥
            byte mkey[] = k.getEncoded();
            Cipher cp = Cipher.getInstance(mode);
            cp.init(Cipher.ENCRYPT_MODE, k);
            byte ptext[] = output.getBytes("UTF8");
            byte ctext[] = cp.doFinal(ptext);

            //将加密后的后缀表达式传送给服务器
            String out1 = BtoA.parseByte2HexStr(ctext);
            out.writeUTF(out1);

            //创建客户端DH算法公、私钥
            DH.createPubAndPriKey("Clientpub.txt","Clientpri.txt");

            //将客户端公钥传给服务器
            FileInputStream fp = new FileInputStream("Clientpub.txt");
            ObjectInputStream bp = new ObjectInputStream(fp);
            Key kp = (Key) bp.readObject();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(kp);
            byte[] kb = baos.toByteArray();
            String pop = BtoA.parseByte2HexStr(kb);
            out.writeUTF(pop);
            Thread.sleep(1000);

            //接收服务器公钥
            String push = in.readUTF();
            byte np[] = AtoB.parseHexStr2Byte(push);
            ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (np));
            Key k2 = (Key)ois.readObject();;
            FileOutputStream f2 = new FileOutputStream("Serverpub.txt");
            ObjectOutputStream b2 = new ObjectOutputStream(f2);
            b2.writeObject(k2);

            //生成共享信息，并生成AES密钥
            SecretKeySpec key = Agree.createKey("Serverpub.txt", "Clientpri.txt");

            //对加密后缀表达式的密钥进行加密，并传给服务器
            cp.init(Cipher.ENCRYPT_MODE, key);
            byte ckey[] = cp.doFinal(mkey);
            String Key = BtoA.parseByte2HexStr(ckey);
            out.writeUTF(Key);

            //接收服务器回答
            String s = in.readUTF();
            System.out.println("客户收到服务器的回答：" + s);
        } catch (Exception e) {
            System.out.println("服务器已断开" + e);
        }
    }
}
